﻿using Common;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using MongoDB;
using MongoDB.Model;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Quartz.Manage
{
    public class ExceptionHandlerMiddleWare
    {
        private readonly RequestDelegate next;
        private readonly IMongoDB _mongoDB;

        /// <summary>
        /// 全局异常捕获
        /// Dgs 2020-01-16 12:10
        /// </summary>
        /// <param name="next"></param>
        /// <param name="logHelper"></param>
        public ExceptionHandlerMiddleWare(RequestDelegate next, IMongoDB mongoDB)
        {
            _mongoDB = mongoDB;
            this.next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await next(context).ConfigureAwait(false);
            }
            catch (System.Exception ex)
            {
                await HandleExceptionAsync(context, ex).ConfigureAwait(false);
            }
        }

        /// <summary>
        /// 判断是否异常
        /// </summary>
        /// <param name="context"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        private async Task HandleExceptionAsync(HttpContext context, System.Exception exception)
        {
            if (exception == null) return;
            await WriteExceptionAsync(context, exception).ConfigureAwait(false);
        }

        /// <summary>
        /// 返回友好的提示
        /// </summary>
        /// <param name="context"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        private async Task WriteExceptionAsync(HttpContext context, System.Exception exception)
        {
            ////记录日志(异步执行)
            //写入错误日志记录
            await _mongoDB.GetCollection<Mongo_TaskErrorModel>("Task_Error").InsertOneAsync(new Mongo_TaskErrorModel
            {
                TaskName = "系统错误",
                CreateTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc),
                GroupName = "系统错误",
                Message = exception.Message,
                TaskUrl = "",
                Method = context.Request.Method,
                RequestBody = exception.StackTrace
            });
            var resMessage = string.Empty;
            //返回友好的提示
            var response = context.Response;
            response.StatusCode = (int)HttpStatusCode.InternalServerError;
            if (context.Request.IsAjax())
            {
                response.ContentType = "application/json;charset=UTF-8";
                await response.WriteAsync(new ApiResult
                {
                    Success = false,
                    Message = resMessage,
                    StatusCode=(int)ApiEnum.Error
                }.ToJson()).ConfigureAwait(false);
            }
            else
            {
                await next(context);
            }
        }

        /// <summary>
        /// 对象转为Xml
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        private static string Object2XmlString(object o)
        {
            StringWriter sw = new StringWriter();
            try
            {
                XmlSerializer serializer = new XmlSerializer(o.GetType());
                serializer.Serialize(sw, o);
            }
            catch
            {
                sw = new StringWriter();
            }
            finally
            {
                sw.Dispose();
            }
            return sw.ToString();
        }


    }

    /// <summary>
    /// 扩展方法，将中间件暴露出去
    /// </summary>
    public static class ExceptionMiddleWare
    {
        /// <summary>
        /// 权限检查
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseException(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ExceptionHandlerMiddleWare>();
        }
    }
}
